/* Copyright [2023] <xwan> */

//
// Created by root on 10/14/23.
//

#include "sql/executor/show_index_executor.h"

#include <memory>

#include "common/log/log.h"
#include "event/session_event.h"
#include "event/sql_event.h"
#include "session/session.h"
#include "sql/operator/string_list_physical_operator.h"
#include "sql/stmt/show_index_stmt.h"
#include "storage/db/db.h"
#include "storage/table/table.h"


RC ShowIndexExecutor::execute(SQLStageEvent *sql_event) {
  RC rc = RC::SUCCESS;
  //  return RC::UNIMPLENMENT;
  Stmt *stmt = sql_event->stmt();
  SessionEvent *session_event = sql_event->session_event();
  Session *session = session_event->session();
  ASSERT(stmt->type() == StmtType::DESC_TABLE,
         "desc table executor can not run this command: %d",
         static_cast<int>(stmt->type()));

  ShowIndexStmt *show_index_stmt = static_cast<ShowIndexStmt *>(stmt);

  SqlResult *sql_result = session_event->sql_result();

  const char *table_name = show_index_stmt->table_name().c_str();

  Db *db = session->get_current_db();
  Table *table = db->find_table(table_name);
  if (table != nullptr) {
    TupleSchema tuple_schema;
    tuple_schema.append_cell(TupleCellSpec("", "Table", "Table"));
    tuple_schema.append_cell(TupleCellSpec("", "Non_unique", "Non_unique"));
    tuple_schema.append_cell(TupleCellSpec("", "Key_name", "Key_name"));
    tuple_schema.append_cell(TupleCellSpec("", "Seq_in_index", "Seq_in_index"));
    tuple_schema.append_cell(TupleCellSpec("", "Column_name", "Column_name"));

    sql_result->set_tuple_schema(tuple_schema);

    auto oper = new StringListPhysicalOperator;
    const TableMeta &table_meta = table->table_meta();

    for (int i = 0; i < table_meta.index_num(); i++) {
      const IndexMeta *index_meta = table_meta.index(i);
      std::string non_unique =
          index_meta->is_unique() ? std::to_string(0) : std::to_string(1);
      for (int j = 0; j < index_meta->field_num(); j++) {
        oper->append({table_name, non_unique, index_meta->name(),
                      std::to_string(j + 1), index_meta->field(j)});
      }
      //      oper->append({table_name, non_unique, index_meta->name(),
      //      std::to_string(1), index_meta->field(0)});
    }

    sql_result->set_operator(unique_ptr<PhysicalOperator>(oper));
  } else {
    sql_result->set_return_code(RC::SCHEMA_TABLE_NOT_EXIST);
    sql_result->set_state_string("Table not exists");
  }
  return rc;
}
